import React, { useEffect, useRef, useState } from 'react';
import { InboxOutlined } from '@ant-design/icons';
import './home.css';
import { Button, message, Progress, Spin } from 'antd';
import useDrag from './useDrag';
import { CHUNK_SIZE } from './constant';  // 默认切片大小
import axiosInstance from './axios';
import axios from 'axios';

// 定义文件上传的状态
const UploadStatus = {
    NOT_STARTED: 'NOT_STARTED',
    UPLOADING: 'UPLOADING',
    PAUSED: 'PAUSED',
};

function Home() {
    let [uploadProgress, setuploadProgress] = useState({});
    const [uploadStatus, setUploadStatus] = useState(UploadStatus.NOT_STARTED);
    const [cancelTokens, setcancelTokens] = useState([]);
    const [filenameWorker, setFilenameWorker] = useState(null);
    const [isCalculatingFileName, setIsCalculatingFileName] = useState(false);
    const [uploadSpeed, setUploadSpeed] = useState(0); // 用于保存网络速度（MB/s）
    const [dynamicChunkSize, setDynamicChunkSize] = useState(CHUNK_SIZE); // 动态切片大小
    const [lastUploadTime, setLastUploadTime] = useState(0); // 上次上传时间

    useEffect(() => {
        const filenameWorker = new Worker('/filenameWorker.jsx');
        setFilenameWorker(filenameWorker);

        // 检测网络类型，并根据网络类型调整切片大小
        const updateNetworkSettings = () => {
            const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
            if (connection) {
                const effectiveType = connection.effectiveType;
                adjustChunkSizeByNetworkType(effectiveType);
                connection.addEventListener('change', () => adjustChunkSizeByNetworkType(connection.effectiveType));
            }
        };

        updateNetworkSettings(); // 初始化时设置网络类型
    }, []);

    const uploadContainerRef = useRef(null);
    const { selectedFile, filePreview, resetFileStatus } = useDrag(uploadContainerRef);

    const pauseUpload = () => {
        setUploadStatus(UploadStatus.PAUSED);
        cancelTokens.forEach(cancelToken => cancelToken.cancel('用户主动暂停了上传'));
    };

    const renderButton = () => {
        switch (uploadStatus) {
            case UploadStatus.NOT_STARTED:
                return <Button onClick={handleUpload}>上传</Button>;
            case UploadStatus.UPLOADING:
                return <Button onClick={pauseUpload}>暂停</Button>;
            case UploadStatus.PAUSED:
                return <Button onClick={handleUpload}>继续</Button>;
            default:
                return null;
        }
    };

    const handleUpload = async () => {
        if (!selectedFile) {
            message.error('你尚未选择任何文件');
            return;
        }
        setUploadStatus(UploadStatus.UPLOADING);
        filenameWorker.postMessage(selectedFile);
        setIsCalculatingFileName(true);

        filenameWorker.onmessage = async (event) => {
            setIsCalculatingFileName(false);
            await uploadFile(selectedFile, event.data, setuploadProgress, resetAllStatus, setcancelTokens);
        };
    };

    const renderProgress = () => {
        if (uploadStatus !== UploadStatus.NOT_STARTED) {
            let totalProgress = renderTotalProgress();
            let chunkProgresses = Object.keys(uploadProgress).map((chunkName, index) => (
                <div key={chunkName}>
                    <span>切片{index}:</span>
                    <Progress percent={uploadProgress[chunkName]} />
                </div>
            ));
            return (
                <>
                    {totalProgress}
                    {chunkProgresses}
                </>
            );
        }
    };

    const renderTotalProgress = () => {
        const percents = Object.values(uploadProgress);
        const totalPercent = Math.round(percents.reduce((acc, curr) => acc + curr, 0) / percents.length);
        return (
            <div>
                <span>总进度：</span>
                <Progress percent={totalPercent} />
            </div>
        );
    };

    const resetAllStatus = () => {
        resetFileStatus();
        setuploadProgress({});
        setUploadStatus(UploadStatus.NOT_STARTED);
    };

    // 上传文件并动态调整切片大小
    async function uploadFile(file, filename, setuploadProgress, resetAllStatus, setcancelTokens) {
        const { needUpload, uploadedChunkList } = await axiosInstance.get(`/verify/${filename}`);
        if (!needUpload) {
            message.success('文件已存在，秒传成功');
            return resetAllStatus();
        }

        const chunks = createFileChunk(file, filename);
        const newCancelTokens = [];
        const requests = chunks.map(({ chunk, chunkFileName }) => {
            const cancelToken = axios.CancelToken.source();
            newCancelTokens.push(cancelToken);

            const existingChunk = uploadedChunkList.find((uploadedChunk) => uploadedChunk.chunkFileName === chunkFileName);
            if (existingChunk) {
                const uploadsedSize = existingChunk.size;
                const remainingChunk = chunk.slice(uploadsedSize);
                if (remainingChunk.size === 0) {
                    return Promise.resolve();
                }
                return createRequest(filename, chunkFileName, remainingChunk, setuploadProgress, cancelToken, uploadsedSize, chunk.size);
            } else {
                return createRequest(filename, chunkFileName, chunk, setuploadProgress, cancelToken, 0, chunk.size);
            }
        });

        setcancelTokens(newCancelTokens);

        try {
            await Promise.all(requests);
            await axiosInstance.get(`/merge/${filename}`);
            message.success('文件上传成功');
            resetAllStatus();
        } catch (error) {
            if (axios.isCancel(error)) {
                message.warning('上传暂停');
            } else {
                message.error('上传出错');
            }
        }
    }

    function createRequest(filename, chunkFileName, chunk, setuploadProgress, cancelToken, start) {
        const startTime = Date.now();
        return axiosInstance.post(`/upload/${filename}`, chunk, {
            headers: {
                'Content-Type': 'application/octet-stream',
            },
            params: {
                chunkFileName,
                start,
            },
            onUploadProgress: (progressEvent) => {
                const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
                setuploadProgress((prevProgress) => ({
                    ...prevProgress,
                    [chunkFileName]: percentCompleted,
                }));

                // 计算网络上传速度 (MB/s)
                const elapsedTime = (Date.now() - startTime) / 1000;  // 计算上传时间
                const speedInMB = Math.round(progressEvent.loaded / elapsedTime / 1024 / 1024); // 转换为MB/s
                setUploadSpeed(speedInMB); // 更新为MB/s

                // 根据网络速度动态调整切片大小
                adjustChunkSize(speedInMB);
            },
            cancelToken: cancelToken.token,
        });
    }

    // 根据网络类型调整切片大小
    function adjustChunkSizeByNetworkType(effectiveType) {
        if (effectiveType > '4g') {
            setDynamicChunkSize(2 * CHUNK_SIZE);  // 网络类型为4G，增加切片大小
        } else if (effectiveType > '3g') {
            setDynamicChunkSize(CHUNK_SIZE);  // 网络类型为3G，保持默认切片大小
        } else {
            setDynamicChunkSize(Math.floor(CHUNK_SIZE / 2));  // 网络类型为2G等，减小切片大小
        }
    }

    // 创建文件切片
    function createFileChunk(file, filename) {
        const chunks = [];
        const count = Math.ceil(file.size / dynamicChunkSize);  // 使用动态切片大小
        for (let i = 0; i < count; i++) {
            const chunk = file.slice(i * dynamicChunkSize, (i + 1) * dynamicChunkSize);
            chunks.push({
                chunk,
                chunkFileName: `${filename}-${i}`,
            });
        }
        return chunks;
    }

    // 渲染文件预览
    function renderFilePreview(filePreview) {
        const { url, type } = filePreview;
        if (url) {
            if (type.startsWith('video/')) {
                return <video src={url} alt='预览' controls />;
            } else if (type.startsWith('image/')) {
                return <img src={url} alt='预览' />;
            } else {
                return url;
            }
        } else {
            return <InboxOutlined />;
        }
    }

    return (
        <div>
            <div className='upload-container' ref={uploadContainerRef}>
                {renderFilePreview(filePreview)}
            </div>
            {renderButton()}
            {isCalculatingFileName && <Spin><span>正在上传中......</span></Spin>}
            <br />
            {renderProgress()}
            {/* 显示上传速度和动态切片大小 */}
            <div>当前上传速度：{uploadSpeed} MB/s</div>
            <div>当前切片大小：{dynamicChunkSize / 1024 / 1024} MB</div>
        </div>
    );
}

export default Home;
